#pragma once
#include "CanServer.hpp"
#include <atomic>
#include <memory>

namespace HardWareDriver
{
class MotorCan
{
  public:
    enum class ErrorCode
    {
        NoError = 0,
        OverVoltage = 1,
        UnderVoltage = 2,
        OverAbsoluteCurrent = 3,
        MOSOverTemperature = 4,
        MCUUnderVoltage = 5,
        WatchDogTriggering = 6,
        SPIInterfaceError = 7,
        FlashBroken = 8,
        UCurrentOverPhase = 9,
        VCurrentOverPhase = 10,
        WCurrentOverPhase = 11,
        CurrentInbalance = 12,
        ConfigInFLASHBroken = 13,
        ProgramInFlashBroken = 14
    };
    enum class ControlMode : unsigned short int
    {
        Current = 0,
        Speed = 1,
        Duty = 2,
        AbsolutePosition = 3,
        RelatTargetPosition = 4,
        RelatePosition = 5,
        Brake = 6,
        HandBrake = 7,
        Zero = 8,
        StopZero = 9,
        CurrentClimb = 10,
        Empty = 0xFFFF
    };
    struct MotorConfig
    {
        int address;
        int poleCount;
    };

  public:
    bool InitDevice(std::shared_ptr<CanServer> canBusInst, MotorConfig cfg);
    float GetRPM();
    bool RequestRPM();
    bool SetRPM(float value);
    bool SetPWM(float precent);
    bool SetCurrent(float mA);
    bool SendHeartBeat();
    MotorCan();
    ~MotorCan();

  private:
    std::shared_ptr<CanServer> bus;
    MotorConfig cfg;
    void OnReceiveCallBack(const can_frame &frame);
    std::atomic<int32_t> erpm;
};
} // namespace HardWareDriver
